package toman;

/**
 * The responsibility of implementations is instantiating, populating and management of transfer objects (TO)<p>
 * Three main tasks:
 *     <ul>
 *         <li>loading a TO for a given unique key
 *         <li>creating a query for loading a single or multiple entities
 *         <li>merging a TO with the underlying data storages (updating)
 *     </ul>
 *
 * <br>
 * User: zslajchrt
 * Date: 21.4.11
 * Time: 15:08
 */
public interface TOMan {

    /**
     * Instantiate a TO for the given TO class and the unique key <code>toId</code>
     * @param toClass the TO class
     * @param toId the unique key
     * @param <T> the TO type
     * @param <K> the unique key type
     * @return the TO
     */
    <T, K> T findTO(Class<T> toClass, K toId);

    /**
     * Update the underlying storage with the data contained in the TO.
     * @param to the TO
     * @param <T> the TO type
     */
    <T> void updateTO(T to);

    /**
     * Creates the query for the given query definition. The query definition can be an SQL, HQL or JPQL fragment (WHERE),
     * or a custom object like an object encapsulating a filter configuration. The query definition is interpreted and handled by
     * an appropriate query engine selected for creating the query.
     * @param toClass the TO class for results returned by the query
     * @param queryDefinition the query definition which should be understood by an appropriate query engine installed to
     * the this TOMan
     * @param <T> the TO type
     * @return
     */
    <T> TOQuery<T> createQuery(Class<T> toClass, Object queryDefinition);

    /**
     * Creates a query from the <code>condition</code> argument and sets parameters with values
     * taken from the context object's properties. For each parameter there must be exactly one property
     * of the context object.
     *
     * @param toClass   TO class of the result
     * @param condition the condition expression (normally it is what follows the WHERE clause). If the condition
     *                  is enclosed in ${...} envelope then it is evaluated as a path to the context bean's property whose value is used
     *                  as the condition.
     * @param context   the context object carrying the parameter values
     * @param <T>
     * @return the query with set parameters taken from the context object
     */
    <T> TOQuery<T> createContextQuery(Class<T> toClass, Object condition, Object context);

    /**
     * This method is responsible for instantiating the given TO class and initializing it with the provided raw data.
     * @param toClass the TO class
     * @param rawData the raw data (e.g. bean, map, array)
     * @param <T> the TO tye
     * @return the TO instance
     */
    <T> T createTOInstance(Class<T> toClass, Object rawData);

    /**
     * This method tries to resolve the given expression object. If it is not recognized as an expression it is returned
     * as the result. Otherwise, the result of the expression evaluation is returned.
     * @param expression the possible expression
     * @param contextObject the context object for evaluating the expression (typically a TO instance on which a property
     * path expression is being evaluated)
     * @return the result of the expression evaluation or the expression argument if not recognized as an expression.
     */
    Object resolvePossibleExpression(Object expression, Object contextObject);

}
